home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Interactive Reference Guide / C-C++ Interactive Reference Guide.iso / c_ref / csource5 / 311_01 / db_dict.c < prev    next >
C/C++ Source or Header  |  1990-04-23  |  10KB  |  503 lines

  1. /****************************************************************************/
  2. /*                                                                          */
  3. /*                                                                          */
  4. /*    db_dict.c - dictionary (symtable manager) routines                  */
  5. /*                  v1.3  (c) 1990  Ken Harris                              */
  6. /*                                                                          */
  7. /*                                                                          */
  8. /****************************************************************************/
  9. /*                                                                          */
  10. /*      This software is made available on an AS-IS basis. Unrestricted     */
  11. /*      use is granted provided that the copyright notice remains intact.   */
  12. /*      The author makes no warranties expressed or implied.                */
  13. /*                                                                          */
  14. /****************************************************************************/
  15.  
  16. #include "dblib.h"
  17.  
  18. #ifdef ANSI
  19. static void strupr(char *);
  20. #else
  21. static void strupr();
  22. #endif
  23. char *calloc();
  24.  
  25. /*
  26.  *    db_dict_hash - Computer hash value for a name
  27.  */
  28.  
  29. static db_dict_hash(name)
  30.  char *name;
  31. {
  32.     long x=0;
  33.  
  34.     while (*name) x += *name++;
  35.     
  36.     return(x % DICT_HASH_SIZE);
  37. }
  38.  
  39.  
  40.  
  41.  
  42. /*
  43.  *    db_dict_init - Initialize a Dictionary
  44.  */
  45.  
  46. DICT db_dict_init()
  47. {    DICT  dict;
  48.     int   i;
  49.  
  50.  
  51.     db_error = 0;
  52.  
  53.     dict = (DICT) calloc(sizeof(struct db_dict_hdr), 1);
  54.     if (!dict)
  55.     {    db_error = DB_ALLOC_ERROR;
  56.         return(NULL);
  57.     }
  58.  
  59.     dict->magic = DICT_MAGIC;
  60.  
  61.     for (i=0; i<DICT_HASH_SIZE; i++)
  62.         dict->htbl[i] = NULL;
  63.  
  64.     return(dict);
  65. }
  66.  
  67. /*
  68.  *    db_dict_add - add a new object to the dictionary
  69.  */
  70.  
  71. void *db_dict_add(dict, name, o_type, d_size, data)
  72.  DICT  dict; 
  73.  char *name; 
  74.  int   o_type; 
  75.  int   d_size; 
  76.  void *data;
  77. {
  78.     short hval, o_size;
  79.     DOBJ  dobj;
  80.     char *o_name, *o_data;
  81.  
  82.  
  83.     db_error = 0;
  84.  
  85.     if (!dict || dict->magic != DICT_MAGIC) 
  86.     {    db_error = DB_INVALID_DICT;
  87.         return(NULL);
  88.     }
  89.  
  90.     if (!name || !*name) 
  91.     {    db_error = DB_INVALID_NAME;
  92.         return(NULL);
  93.     }
  94.  
  95.     strupr(name);
  96.     hval = db_dict_hash(name);
  97.  
  98.     if (db_dict_find(dict, name, o_type))
  99.     {    db_dict_delete(dict, name, o_type);
  100.         if (db_error) return(NULL);
  101.     }
  102.     else
  103.         db_error = 0;
  104.  
  105.     o_size = sizeof(struct db_dict_obj) + strlen(name) + d_size;
  106.     dobj   = (DOBJ) calloc(o_size, 1);
  107.     if (!dobj)
  108.     {    db_error = DB_ALLOC_ERROR;
  109.         return(NULL);
  110.     }
  111.  
  112.     dobj->o_type     = o_type;
  113.     dobj->next       = dict->htbl[hval];
  114.     dict->htbl[hval] = dobj;
  115.     dobj->n_size     = strlen(name);
  116.     dobj->d_size     = d_size;
  117.  
  118.     o_data           = &dobj->data;
  119.     o_name           = o_data + dobj->d_size;
  120.  
  121.     strcpy(o_name, name);
  122.     if (data) memcpy(o_data, data, d_size);
  123.  
  124.     return(o_data);
  125. }
  126.  
  127. /*
  128.  *    db_dict_delete - delete an object by name
  129.  */
  130.  
  131. void db_dict_delete(dict, name, o_type)
  132.  DICT  dict; 
  133.  char *name; 
  134.  int   o_type;
  135. {
  136.     DOBJ  prev, cur, next;
  137.     short hval;
  138.     char *cur_name;
  139.  
  140.  
  141.     db_error = 0;
  142.  
  143.     if (!dict || dict->magic != DICT_MAGIC) 
  144.     {    db_error = DB_INVALID_DICT;
  145.         return;
  146.     }
  147.  
  148.     if (!name || !*name)
  149.     {    db_error = DB_INVALID_NAME;
  150.         return;
  151.     }
  152.  
  153.     strupr(name);
  154.  
  155.     hval = db_dict_hash(name);
  156.     prev = NULL;
  157.     cur  = dict->htbl[hval];
  158.  
  159.     while (cur)
  160.     {    cur_name = &cur->data + cur->d_size;    
  161.         if (strcmp(cur_name, name)==0 &&
  162.             (cur->o_type==o_type || o_type==0))
  163.         {    if (prev)
  164.                 prev->next       = cur->next;
  165.             else
  166.                 dict->htbl[hval] = cur->next;
  167.  
  168.             next = cur->next;
  169.             free(cur);
  170.             cur = next;
  171.         }
  172.         else
  173.         {    prev = cur;
  174.             cur  = cur->next;
  175.         }
  176.     }
  177. }
  178.  
  179. /*
  180.  *    db_dict_delete_all - delete all objects of a type
  181.  */
  182.  
  183. void db_dict_delete_all(dict, o_type)
  184.  DICT  dict; 
  185.  int   o_type;
  186. {
  187.     DOBJ  prev, cur, next;
  188.     short hval, i;
  189.  
  190.  
  191.     db_error = 0;
  192.  
  193.     if (!dict || dict->magic != DICT_MAGIC) 
  194.     {    db_error = DB_INVALID_DICT;
  195.         return;
  196.     }
  197.  
  198.     for (i=0; i<DICT_HASH_SIZE; i++)
  199.     {    prev = NULL;
  200.         cur  = dict->htbl[i];
  201.  
  202.         while (cur)
  203.         {    if (cur->o_type==o_type || o_type==0)
  204.             {    if (prev)
  205.                     prev->next    = cur->next;
  206.                 else
  207.                     dict->htbl[i] = cur->next;
  208.  
  209.                 next = cur->next;
  210.                 free(cur);
  211.                 cur = next;
  212.             }
  213.             else
  214.             {    prev = cur;
  215.                 cur  = cur->next;
  216.             }
  217.         }
  218.     }
  219. }
  220.  
  221. /*
  222.  *    db_dict_find - Find a object by name
  223.  */
  224.  
  225. void *db_dict_find(dict, name, o_type)
  226.  DICT  dict; 
  227.  char *name; 
  228.  int   o_type;
  229. {
  230.     DOBJ  dobj;
  231.     short hval;
  232.     char *o_name;
  233.  
  234.  
  235.     db_error = 0;
  236.  
  237.     if (!dict || dict->magic != DICT_MAGIC) 
  238.     {    db_error = DB_INVALID_DICT;
  239.         return(NULL);
  240.     }
  241.  
  242.     if (!name || !*name)
  243.     {    db_error = DB_INVALID_NAME;
  244.         return(NULL);
  245.     }
  246.  
  247.     strupr(name);
  248.  
  249.     hval = db_dict_hash(name);
  250.     dobj = dict->htbl[hval];
  251.  
  252.     while (dobj)
  253.     {    o_name = &dobj->data + dobj->d_size;
  254.         if (strcmp(o_name,name)==0 &&
  255.             (dobj->o_type==o_type || o_type==0))
  256.             return(&dobj->data);
  257.         
  258.         dobj = dobj->next;
  259.     }
  260.  
  261.     db_error = DB_REC_NOT_FOUND;
  262.     return(NULL);
  263. }
  264.  
  265. /*
  266.  *    db_dict_find_all - Find all objects by type
  267.  */
  268.  
  269. db_dict_find_all(dict, o_type, nlist, dlist)
  270.  DICT   dict; 
  271.  int    o_type; 
  272.  char **nlist[]; 
  273.  void **dlist[];
  274. {
  275.     DOBJ  dobj;
  276.     short i, j, cnt;
  277.     char  *tmp, *o_name, *o_data;
  278.  
  279.  
  280.     db_error = 0;
  281.  
  282.     if (!dict || dict->magic != DICT_MAGIC) 
  283.     {    db_error = DB_INVALID_DICT;
  284.         return(0);
  285.     }
  286.  
  287.     for (i=0, cnt=0; i<DICT_HASH_SIZE; i++)
  288.     {    dobj = dict->htbl[i];
  289.         while (dobj)
  290.         {    if (dobj->o_type==o_type || o_type==0) cnt++;
  291.             dobj = dobj->next;
  292.         }
  293.     }
  294.  
  295.     if (!cnt)
  296.     {    db_error = DB_REC_NOT_FOUND;
  297.         *nlist = NULL;
  298.         *dlist = NULL;
  299.         return(0);
  300.     }
  301.  
  302.     *nlist = (char **) calloc(sizeof(char *), cnt);
  303.     if (!*nlist)
  304.     {    db_error = DB_ALLOC_ERROR;
  305.         return(0);
  306.     }
  307.  
  308.     *dlist = (void **) calloc(sizeof(char *), cnt);
  309.     if (!*dlist) 
  310.     {    db_error = DB_ALLOC_ERROR;
  311.         free(*nlist);
  312.         return(0);
  313.     }
  314.     for (i=0, cnt=0; i<DICT_HASH_SIZE; i++)
  315.     {    dobj = dict->htbl[i];
  316.         while (dobj)
  317.         {    if (dobj->o_type==o_type || o_type==0)
  318.             {    o_data = &dobj->data;
  319.                 o_name = o_data + dobj->d_size;
  320.                  (*nlist)[cnt] = o_name;
  321.                 (*dlist)[cnt] = o_data;
  322.                 cnt++;
  323.  
  324.                 for (j=cnt-1; j>0; j--)
  325.                 {    if (strcmp((*nlist)[j],(*nlist)[j-1])<0)
  326.                     {    tmp           = (*nlist)[j];
  327.                         (*nlist)[j]   = (*nlist)[j-1];
  328.                         (*nlist)[j-1] = tmp;
  329.                         tmp           = (*dlist)[j];
  330.                         (*dlist)[j]   = (*dlist)[j-1];
  331.                         (*dlist)[j-1] = tmp;
  332.                     }
  333.                     else
  334.                         break;
  335.                 }
  336.             }
  337.             dobj = dobj->next;
  338.         }
  339.     }
  340.     return(cnt);
  341. }
  342.  
  343. /*
  344.  *    db_dict_load - Load dictionary entries from a file
  345.  */
  346.  
  347. void db_dict_load(dict, path, fname)
  348.  DICT  dict; 
  349.  char *path, *fname;
  350. {
  351.     DATA_FILE df;
  352.     FILE_HDR  fh;
  353.     DOBJ      dobj;
  354.     char     *o_name, *buf;
  355.     unsigned  o_size, hval;
  356.  
  357.  
  358.     db_error = 0;
  359.  
  360.     if (!dict || dict->magic != DICT_MAGIC) 
  361.     {    db_error = DB_INVALID_DICT;
  362.         return;
  363.     }
  364.  
  365.     if (!fname || !*fname)
  366.     {    db_error = DB_INVALID_NAME;
  367.         return;
  368.     }
  369.  
  370.     df = db_open(path, fname);
  371.     if (db_error) return;
  372.  
  373.     fh  = (FILE_HDR)df->df_fhdr;
  374.     buf = (char *)calloc(fh->fh_rec_size, 1);
  375.     if (!buf)
  376.     {    db_error = DB_ALLOC_ERROR;
  377.         return;
  378.     }
  379.  
  380.     db_read_first(df, buf, &o_size);
  381.     while (!db_error)
  382.     {    dobj = (DOBJ) calloc(o_size, 1);
  383.         if (!dobj) 
  384.         {    db_error = DB_ALLOC_ERROR;
  385.             free(buf);
  386.             return;
  387.         }
  388.  
  389.         memcpy(dobj, buf, o_size);
  390.  
  391.         o_name           = &dobj->data + dobj->d_size;
  392.         hval             = db_dict_hash(o_name);
  393.         dobj->next       = dict->htbl[hval];
  394.         dict->htbl[hval] = dobj;
  395.  
  396.         db_read_next(df, buf, &o_size);
  397.     }
  398.     if (db_error = DB_END_OF_FILE) db_error = 0;
  399.     free(buf);
  400.     db_close(df);
  401. }
  402.  
  403. /*
  404.  *    db_dict_dump - Dump dictionary objects to a file
  405.  */
  406.  
  407. void db_dict_dump(dict, path, fname)
  408.  DICT  dict; 
  409.  char *path, *fname;
  410. {
  411.     DATA_FILE df;
  412.     DOBJ      dobj;
  413.     unsigned  o_size, i, cnt, max_size;
  414.     char      options[50];
  415.  
  416.     db_error = 0;
  417.  
  418.     if (!dict || dict->magic != DICT_MAGIC) 
  419.     {    db_error = DB_INVALID_DICT;
  420.         return;
  421.     }
  422.  
  423.     if (!fname || !*fname)
  424.     {    db_error = DB_INVALID_NAME;
  425.         return;
  426.     }
  427.  
  428.     for (i=0, cnt=0, max_size=0; i<DICT_HASH_SIZE; i++)
  429.     {    dobj = dict->htbl[i];
  430.         while (dobj)
  431.         {    o_size = sizeof(struct db_dict_obj) + dobj->d_size
  432.                    + dobj->n_size;
  433.             if (o_size > max_size) max_size = o_size;    
  434.             cnt++;
  435.             dobj = dobj->next;
  436.         }
  437.     }
  438.  
  439.     if (!cnt)
  440.     {    db_error = DB_REC_NOT_FOUND;
  441.         return;
  442.     }
  443.  
  444.     sprintf(options,"VAR, REC=%d", max_size);
  445.     df = db_create(path, fname, options);
  446.     if (db_error) return;
  447.  
  448.     for (i=0; i<DICT_HASH_SIZE; i++)
  449.     {    dobj = dict->htbl[i];
  450.         while (dobj)
  451.         {    o_size = sizeof(struct db_dict_obj) + dobj->d_size
  452.                    + dobj->n_size;
  453.             db_add(df, dobj, o_size);
  454.             if (db_error) return;
  455.             dobj = dobj->next;
  456.         }
  457.     }
  458.     db_close(df);
  459. }
  460.  
  461. /*
  462.  *    db_dict_close - Close a dictionary and dispose of its contents
  463.  */
  464.  
  465. void db_dict_close(dict)
  466.  DICT dict;
  467. {
  468.     DOBJ  dobj, next;
  469.     short i;
  470.  
  471.  
  472.     db_error = 0;
  473.  
  474.     if (!dict || dict->magic != DICT_MAGIC) 
  475.     {    db_error = DB_INVALID_DICT;
  476.         return;
  477.     }
  478.  
  479.     for (i=0; i<DICT_HASH_SIZE; i++)
  480.     {    dobj = dict->htbl[i];
  481.         while (dobj)
  482.         {    next = dobj->next;
  483.             free(dobj);
  484.             dobj = next;
  485.         }
  486.     }
  487.     dict->magic = 0;
  488.     free(dict);
  489. }
  490.  
  491. /*
  492.  *    strupr - convert string to upper case
  493.  */
  494.  
  495. static void strupr(str)
  496.  char *str;
  497. {
  498.     while (*str)
  499.     {    if (islower(*str)) *str = toupper(*str);
  500.         str++;
  501.     }
  502. }
  503.